﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.Transactions;
using System.Data;

namespace Defect_Tracking_System.Models
{
    public class ClientManagement
    {
        private static ClientManagement instance;

        private ClientManagement()
        {
        }

        public static ClientManagement GetInstance()
        {
            if (instance == null)
            {
                instance = new ClientManagement();
            }
            return instance;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Acc"></param>
        public void DeleteClient(Client client)
        {
            DefectTrackingSystemEntities Entities = new DefectTrackingSystemEntities();

            var defect = Entities.Defects.Where(d => d.Originator == client.ClientId);

            if (defect.Count() > 0)
            {
                throw new Exception("This client is originator of some defects. You can't delete this client!");
            }

            Entities.Clients.DeleteObject(client);

            using (TransactionScope transaction = new TransactionScope())
            {
                try
                {
                    Entities.SaveChanges();
                    transaction.Complete();
                    Entities.AcceptAllChanges();
                }
                catch (OptimisticConcurrencyException e)
                {
                    Entities.SaveChanges();
                    throw new Exception(e.Message);
                }
            }
        }

        public void AddClient(ClientModel Model)
        {
            DefectTrackingSystemEntities Entities = new DefectTrackingSystemEntities();

            Client temp = GetClientByEmail(Model.Email);

            if (temp != null)
            {
                throw new Exception("Email is exited");
            }

            Client client = new Client();
            client.ClientId = Guid.NewGuid();
            client.GroupId = Guid.Parse(Model.GroupId);
            client.FirstName = Model.FirstName;
            client.LastName = Model.LastName;
            client.Company = Model.Company;
            client.Email = Model.Email;
            client.CreatedDate = DateTime.Now;

            Entities.Clients.AddObject(client);
            Entities.SaveChanges();
        }

        public IQueryable<Client> GetClients(String GroupId)
        {
            DefectTrackingSystemEntities Entities = new DefectTrackingSystemEntities();

            Guid GuidId = Guid.Parse(GroupId);
            return from C in Entities.Clients
                   where C.GroupId == GuidId
                   orderby C.Company
                   select C;
        }

        public IQueryable<Client> Search(String Keyword, String UserName)
        {
            DefectTrackingSystemEntities Entities = new DefectTrackingSystemEntities();

            Account account = AccountManagement.GetInstance().GetUserByUserName(UserName);

            if (account == null)
            {
                throw new Exception("User Name is not exited");
            }

            return from c in Entities.Clients
                   where ((c.FirstName + " " + c.LastName).Contains(Keyword) || c.Company.Contains(Keyword) || c.Email.Contains(Keyword)) && (c.GroupId == account.GroupId)
                   select c;
        }

        public void EditClient(ClientModel model)
        {
            DefectTrackingSystemEntities Entities = new DefectTrackingSystemEntities();
            Guid id = Guid.Parse(model.ClientId);
            Client client = Entities.Clients.FirstOrDefault(c => c.ClientId == id);

            if (client == null)
            {
                throw new Exception("Client is not exited");
            }

            if (client.Email != model.Email)
            {
                Client temp = GetClientByEmail(model.Email);

                if (temp != null)
                {
                    throw new Exception("Email is exited");
                }
            }

            client.FirstName = model.FirstName;
            client.LastName = model.LastName;
            client.Company = model.Company;
            client.Email = model.Email;

            Entities.SaveChanges();
        }

        public Client GetClient(String ClientId)
        {
            DefectTrackingSystemEntities Entities = new DefectTrackingSystemEntities();

            Guid guid;
            Guid.TryParse(ClientId, out guid);

            return Entities.Clients.FirstOrDefault(c => c.ClientId == guid);
        }

        public Client GetClientByEmail(String Email)
        {
            DefectTrackingSystemEntities Entities = new DefectTrackingSystemEntities();
            return Entities.Clients.FirstOrDefault(c => c.Email == Email);
        }

        public ClientModel GetClientModel(string ClientId)
        {
            ClientModel model = new ClientModel();

            Client client = GetClient(ClientId);

            if (client == null)
            {
                throw new Exception("Client is not exited");
            }

            model.FirstName = client.FirstName;
            model.LastName = client.LastName;
            model.Email = client.Email;
            model.Company = client.Company;

            return model;
        }
    }


    public class ClientModel
    {
        public String ClientId { get; set; }

        [DisplayName("GroupId")]
        public String GroupId { get; set; }

        [Required]
        [DisplayName("First Name")]
        public string FirstName { get; set; }

        [Required]
        [DisplayName("Last Name")]
        public string LastName { get; set; }

        [Required]
        [DisplayName("Company")]
        public string Company { get; set; }

        [Required]
        [DataType(DataType.EmailAddress)]
        [DisplayName("Email address")]
        [RegularExpression(@"^([0-9a-zA-Z]([-\.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$", ErrorMessage = "Email is invalid")]
        public string Email { get; set; }
    }
}